<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>微舆</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Arial', sans-serif;
            background-color: #ffffff;
            color: #000000;
            line-height: 1.6;
            overflow-x: hidden;
        }

        .container {
            max-width: 100vw;
            height: 100vh; /* 固定高度为视口高度 */
            display: flex;
            flex-direction: column;
            border: 2px solid #000000;
            overflow: hidden; /* 防止整体滚动 */
        }

        /* 搜索框区域 */
        .search-section {
            border-bottom: 2px solid #000000;
            padding: 20px;
            background-color: #ffffff;
        }

        .search-title {
            font-size: 24px;
            font-weight: bold;
            text-align: center;
            margin-bottom: 20px;
            letter-spacing: 1px;
        }

        .search-row {
            display: flex;
            align-items: stretch;
            gap: 12px;
            max-width: 950px;
            margin: 0 auto 10px;
        }

        .config-button {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 24px;
            border: 2px solid #000000;
            background-color: #ffffff;
            color: #000000;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
            min-width: 120px;
        }

        .config-button:hover {
            background-color: #000000;
            color: #ffffff;
        }

        .config-password-wrapper {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .config-password-wrapper .config-field-input {
            flex: 1;
        }

        .config-password-toggle {
            padding: 8px 14px;
            border: 2px solid #000000;
            background-color: #ffffff;
            cursor: pointer;
            font-size: 12px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .config-password-toggle:hover,
        .config-password-toggle.revealed {
            background-color: #000000;
            color: #ffffff;
        }

        .search-box {
            display: flex;
            flex: 1;
            border: 2px solid #000000;
        }

        .search-input {
            flex: 1;
            padding: 15px;
            border: none;
            outline: none;
            font-size: 16px;
            background-color: #ffffff;
        }

        .search-button {
            padding: 15px 30px;
            border: none;
            border-left: 2px solid #000000;
            background-color: #000000;
            color: #ffffff;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .search-button:hover {
            background-color: #333333;
        }

        .search-button:disabled {
            background-color: #666666;
            cursor: not-allowed;
        }

        .upload-button {
            padding: 15px 20px;
            border: none;
            border-left: 2px solid #000000;
            background-color: #ffffff;
            color: #000000;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .upload-button:hover {
            background-color: #f0f0f0;
        }

        .upload-button input[type="file"] {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            opacity: 0;
            cursor: pointer;
        }

        .upload-status {
            font-size: 12px;
            margin: 10px auto 0;
            text-align: center;
            color: #666666;
            max-width: 950px;
        }

        .upload-status.success {
            color: #4a6741;
        }

        .upload-status.error {
            color: #8b4513;
        }

        /* 主内容区域 */
        .main-content {
            flex: 1;
            display: flex;
            height: calc(100vh - 140px);
            min-height: 0; /* 允许子元素缩小 */
        }

        /* 嵌入页面区域 */
        .embedded-section {
            flex: 1.8; /* 稍微缩小左侧区域 */
            border-right: 2px solid #000000;
            background-color: #ffffff;
            position: relative;
        }

        .embedded-header {
            padding: 15px;
            border-bottom: 2px solid #000000;
            background-color: #ffffff;
            font-weight: bold;
            text-align: center;
        }

        .embedded-content {
            height: calc(100% - 60px);
            position: relative;
            overflow: hidden;
        }

        /* 控制台输出区域 */
        .console-section {
            flex: 1.2; /* 稍微扩大右侧区域 */
            display: flex;
            flex-direction: column;
            background-color: #ffffff;
            min-height: 0; /* 允许子元素缩小 */
            overflow: hidden; /* 防止内容溢出 */
        }

        /* 应用切换按钮 */
        .app-switcher {
            display: flex;
            border-bottom: 2px solid #000000;
        }

        .app-button {
            flex: 1;
            padding: 15px;
            border: none;
            border-right: 2px solid #000000;
            background-color: #ffffff;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
            position: relative;
        }

        .app-button:last-child {
            border-right: none;
        }

        .app-button.active {
            background-color: #000000;
            color: #ffffff;
        }

        .app-button:not(.active):hover {
            background-color: #f0f0f0;
        }

        .app-button.locked {
            background-color: #f5f5f5;
            color: #999999;
            cursor: not-allowed;
            position: relative;
        }

        .app-button.locked:hover {
            background-color: #f5f5f5;
        }

        .app-button.locked::after {
            content: "";
            position: absolute;
            top: 50%;
            right: 10px;
            transform: translateY(-50%);
            font-size: 12px;
        }

        .app-button.locked .status-indicator {
            background-color: #cccccc;
        }

        .status-indicator {
            position: absolute;
            top: 5px;
            right: 5px;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background-color: #ff0000;
        }

        .status-indicator.running {
            background-color: #00ff00;
        }

        .status-indicator.starting {
            background-color: #ffff00;
        }

        /* 控制台输出 */
        .console-output {
            flex: 1;
            padding: 15px;
            background-color: #000000;
            color: #00ff00;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            overflow-y: auto;
            overflow-x: hidden;
            white-space: pre-wrap;
            word-break: break-all;
            min-height: 0; /* 允许内容缩小 */
        }

        .console-line {
            margin-bottom: 2px;
        }

        /* 状态信息 */
        .status-bar {
            padding: 10px 20px;
            border-top: 2px solid #000000;
            background-color: #ffffff;
            font-size: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .config-modal-overlay {
            position: fixed;
            inset: 0;
            background-color: rgba(0, 0, 0, 0.35);
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 999;
            padding: 20px;
        }

        .config-modal-overlay.visible {
            display: flex;
        }

        .config-modal {
            background-color: #ffffff;
            border: 2px solid #000000;
            width: 720px;
            max-width: 90vw;
            max-height: 85vh;
            display: flex;
            flex-direction: column;
            box-shadow: 6px 6px 0 #000000;
        }

        .config-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px 20px;
            border-bottom: 2px solid #000000;
            background-color: #ffffff;
        }

        .config-modal-title {
            font-size: 18px;
            font-weight: bold;
        }

        .config-modal-actions {
            display: flex;
            gap: 10px;
            align-items: center;
        }

        .config-close-button {
            width: 32px;
            height: 32px;
            border: 2px solid #000000;
            background-color: #ffffff;
            font-size: 18px;
            line-height: 1;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .config-close-button:hover {
            background-color: #000000;
            color: #ffffff;
        }

        .config-close-button:disabled {
            opacity: 0.4;
            cursor: not-allowed;
            background-color: #f0f0f0;
            color: #666666;
        }

        .config-secondary-button {
            padding: 8px 18px;
            border: 2px solid #000000;
            background-color: #ffffff;
            color: #000000;
            cursor: pointer;
            font-size: 13px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .config-secondary-button:hover {
            background-color: #f0f0f0;
        }

        .config-modal-body {
            padding: 20px;
            overflow-y: auto;
        }

        .config-group {
            border: 2px solid #000000;
            padding: 16px;
            margin-bottom: 16px;
            background-color: #ffffff;
        }

        .config-group-title {
            font-size: 15px;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .config-group-subtitle {
            font-size: 12px;
            color: #555555;
            margin-bottom: 12px;
        }

        .config-field {
            display: flex;
            flex-direction: column;
            margin-bottom: 12px;
        }

        .config-field-label {
            font-size: 12px;
            font-weight: bold;
            margin-bottom: 6px;
        }

        .config-field-input {
            padding: 10px 12px;
            border: 2px solid #000000;
            font-size: 14px;
            background-color: #ffffff;
        }

        .config-field-input:focus {
            outline: none;
            border-color: #333333;
        }

        .config-field-input[data-field-type="select"] {
            cursor: pointer;
            appearance: none;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23333' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
            background-repeat: no-repeat;
            background-position: right 12px center;
            padding-right: 36px;
        }

        .config-modal-footer {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px 20px;
            border-top: 2px solid #000000;
            background-color: #ffffff;
        }

        .config-modal-footer-actions {
            display: flex;
            gap: 10px;
        }

        .config-status-message {
            font-size: 12px;
            color: #555555;
        }

        .config-status-message.error {
            color: #8b4513;
        }

        .config-status-message.success {
            color: #4a6741;
        }

        .config-save-button {
            padding: 10px 24px;
            border: none;
            background-color: #000000;
            color: #ffffff;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .config-save-button:hover {
            background-color: #333333;
        }

        .config-save-button:disabled {
            background-color: #666666;
            cursor: not-allowed;
        }

        .config-start-button {
            padding: 10px 24px;
            border: none;
            background-color: #000000;
            color: #ffffff;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .config-start-button:hover {
            background-color: #333333;
        }

        .config-start-button:disabled {
            background-color: #666666;
            cursor: not-allowed;
        }

        .loading {
            display: inline-block;
            width: 12px;
            height: 12px;
            border: 2px solid #000000;
            border-radius: 50%;
            border-top-color: transparent;
            animation: spin 1s ease-in-out infinite;
        }

        /* 专门用于报告状态的加载指示器，不会让整个容器旋转 */
        .report-loading-spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid #ffa500;
            border-radius: 50%;
            border-top-color: transparent;
            animation: spin 1s ease-in-out infinite;
            margin-right: 8px;
            vertical-align: middle;
        }

        /* 任务进度条样式 */
        .task-progress-container {
            margin: 0; /* 移除margin，使用父容器的gap控制间距 */
            padding: 20px;
            border: 2px solid #000000;
            background-color: #f5f5f0;
        }

        .task-progress-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 15px;
            font-weight: bold;
            font-size: 16px;
        }

        .task-progress-title {
            display: flex;
            align-items: center;
            flex-shrink: 0;
        }

        .task-progress-bar {
            width: 200px;
            height: 20px;
            background-color: #e8e8e0;
            border: 1px solid #666666;
            margin-left: 20px;
            position: relative;
            overflow: hidden;
            border-radius: 3px;
            flex-shrink: 0;
        }

        .task-progress-fill {
            height: 100%;
            background: linear-gradient(90deg, #6b8a5a 0%, #8fb584 100%);
            transition: width 0.5s ease;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
            min-width: 2px; /* 确保即使是0%也有一点显示 */
        }

        .task-progress-text {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #000000;
            font-weight: bold;
            font-size: 12px;
            z-index: 2;
            pointer-events: none;
        }

        .task-info-line {
            display: flex;
            align-items: center;
            margin-top: 10px;
            font-size: 13px;
            padding: 8px;
            background-color: #f0f0e8;
            border: 1px solid #d0d0c0;
            border-radius: 3px;
        }

        .task-info-item {
            display: flex;
            align-items: center;
            margin-right: 30px;
        }

        .task-info-item:last-child {
            margin-right: 0;
        }

        .task-info-label {
            font-weight: bold;
            color: #666;
            margin-right: 8px;
        }

        .task-info-value {
            color: #000;
        }

        .task-status-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 15px;
            font-size: 12px;
            font-weight: bold;
            margin-left: 10px;
        }

        .task-status-running {
            background-color: #fff3cd;
            color: #856404;
            border: 1px solid #ffeaa7;
        }

        .task-status-completed {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .task-status-error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .task-error-message {
            margin-top: 15px;
            padding: 10px;
            background-color: #ffe6e6;
            border-left: 4px solid #ff4444;
            border-radius: 3px;
            font-size: 13px;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            .main-content {
                flex-direction: column;
                height: auto;
            }

            .embedded-section {
                border-right: none;
                border-bottom: 2px solid #000000;
                height: 400px;
            }

            .console-section {
                height: 300px;
            }
        }

        /* 消息提示 */
        .message {
            position: fixed;
            top: 20px;
            right: 0px;
            padding: 15px 20px;
            border: 2px solid #000000;
            background-color: #ffffff;
            color: #000000;
            font-weight: bold;
            transform: translateX(100%);
            transition: transform 0.3s ease;
            z-index: 1000;
        }

        .message.show {
            transform: translateX(-5%);
        }

        .message.success {
            border-color: #00aa00;
            background-color: #f0fff0;
        }

        .message.error {
            border-color: #aa0000;
            background-color: #fff0f0;
        }

        /* Forum Engine 专用样式 */
        .forum-container {
            display: none;
            height: 100%;
            flex-direction: column;
        }

        .forum-container.active {
            display: flex;
        }

        .forum-chat-area {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: 20px;
            overflow-y: auto;
        }

        .forum-message {
            margin-bottom: 20px;
            min-width: 200px;
            max-width: 85%;
            padding: 15px;
            border: 2px solid #000000;
            border-radius: 0;
            word-wrap: break-word;
        }

        .forum-message.user {
            align-self: flex-end;
            background-color: #000000;
            color: #ffffff;
        }

        .forum-message.system {
            align-self: flex-start;
            background-color:rgb(182 182 182);
            color: #000000;
            border-color:rgb(62 62 62);
        }

        .forum-message.agent {
            align-self: stretch; /* 占满整个宽度 */
            color: #000000;
            width: 100%; /* 确保占满宽度 */
            max-width: 100%; /* 移除最大宽度限制 */
            margin: 0 0 20px 0; /* 移除左右边距 */
        }

        /* 不同Engine的颜色区分 */
        .forum-message.agent:has(.forum-message-header:contains("Query Engine")) {
            background-color: #eaf1f8;
            border-color: #608ab1;
        }

        .forum-message.agent:has(.forum-message-header:contains("QUERY Engine")) {
            background-color: #eaf1f8;
            border-color: #608ab1;
        }

        .forum-message.agent:has(.forum-message-header:contains("Insight Engine")) {
            background-color: #f2ebf3;
            border-color: #8e6a9f;
        }

        .forum-message.agent:has(.forum-message-header:contains("INSIGHT Engine")) {
            background-color: #f2ebf3;
            border-color: #8e6a9f;
        }

        .forum-message.agent:has(.forum-message-header:contains("Media Engine")) {
            background-color: #ebf2ea;
            border-color: #6a9a6e;
        }

        .forum-message.agent:has(.forum-message-header:contains("MEDIA Engine")) {
            background-color: #ebf2ea;
            border-color: #6a9a6e;
        }

        /* 备用方案：通过JavaScript添加的类 */
        .forum-message.query-engine {
            background-color: #eaf1f8;
            border-color: #608ab1;
        }

        .forum-message.insight-engine {
            background-color: #f2ebf3;
            border-color: #8e6a9f;
        }

        .forum-message.media-engine {
            background-color: #ebf2ea;
            border-color: #6a9a6e;
        }

        .forum-message.agent.QUERY {
            background-color: #eaf1f8;
            border-color: #608ab1;
        }

        .forum-message.agent.query-engine {
            background-color: #eaf1f8;
            border-color: #608ab1;
        }

        .forum-message.agent.MEDIA {
            background-color: #ebf2ea;
            border-color: #6a9a6e;
        }

        .forum-message.agent.media-engine {
            background-color: #ebf2ea;
            border-color: #6a9a6e;
        }

        .forum-message.agent.INSIGHT {
            background-color: #f2ebf3;
            border-color: #8e6a9f;
        }

        .forum-message.agent.insight-engine {
            background-color: #f2ebf3;
            border-color: #8e6a9f;
        }
        
        /* HOST主持人样式 */
        .forum-message.host {
            align-self: stretch;
            background-color: #fff8dc;  /* 浅黄色背景 */
            border-color: #daa520;  /* 金色边框 */
            color: #000000;
            width: 100%;
            max-width: 100%;
            margin: 0 0 20px 0;
            font-style: italic;  /* 斜体字体显示主持人发言 */
        }

        .forum-message-header {
            font-weight: bold;
            margin-bottom: 8px;
            font-size: 12px;
            opacity: 0.8;
        }

        .forum-message-content {
            line-height: 1.4;
            word-wrap: break-word;
        }

        .forum-timestamp {
            font-size: 10px;
            opacity: 0.6;
            margin-top: 5px;
        }

        /* Report Engine 专用样式 */
        .report-container {
            display: none;
            height: 100%;
            flex-direction: column;
            position: relative;
        }

        .report-container.active {
            display: flex;
        }

        .report-content {
            flex: 1;
            padding: 10px 20px 20px 20px; /* 减少上边距 */
            overflow-y: auto;
            overflow-x: hidden;
            background-color: #ffffff;
            display: flex;
            flex-direction: column;
            min-height: 0; /* 允许子元素缩小 */
            gap: 15px; /* 统一子元素间距 */
        }

        .report-controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            padding: 15px;
            border-bottom: 2px solid #000000;
            background-color: #f8f9fa;
        }

        .report-button {
            padding: 10px 20px;
            border: 2px solid #000000;
            background-color: #ffffff;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .report-button:hover {
            background-color: #f0f0f0;
        }

        .report-button:disabled {
            background-color: #e0e0e0;
            cursor: not-allowed;
        }

        .report-button.primary {
            background-color: #000000;
            color: #ffffff;
        }

        .report-button.primary:hover {
            background-color: #333333;
        }

        .report-status {
            padding: 15px;
            margin: 0; /* 移除margin，使用父容器的gap控制间距 */
            border: 2px solid #000000;
            background-color: #f8f9fa;
            font-family: 'Courier New', monospace;
        }

        .report-status.loading {
            border-color: #b8860b;
            background-color: #faf5e6;
            /* 确保loading状态的报告框不会旋转 */
            animation: none;
        }

        .report-status.success {
            border-color: #4a6741;
            background-color: #f0f5ed;
        }

        .report-status.error {
            border-color: #8b4513;
            background-color: #fdf5e6;
        }

        .report-preview {
            border: 2px solid #000000;
            background-color: #ffffff;
            min-height: 400px;
            max-height: none; /* 移除最大高度限制 */
            overflow-y: hidden; /* 强制不显示垂直滚动条 */
            overflow-x: hidden; /* 强制不显示水平滚动条 */
            flex: 1; /* 让预览区域占用剩余空间 */
        }

        .report-preview iframe {
            width: 100%;
            min-height: 400px;
            border: none;
            /* 让iframe自适应内容高度 */
            height: auto;
            /* 强制不显示滚动条 */
            overflow: hidden;
            scrollbar-width: none; /* Firefox */
            -ms-overflow-style: none; /* IE and Edge */
        }
        
        /* 隐藏webkit浏览器的滚动条 */
        .report-preview iframe::-webkit-scrollbar {
            display: none;
        }

        .report-loading {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 200px;
            color: #666;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 搜索框区域 -->
        <div class="search-section">
            <div class="search-title">微舆 - 致力于打造简洁通用的舆情分析平台</div>
            <div class="search-row">
                <button class="config-button" id="openConfigButton">LLM 配置</button>
                <div class="search-box">
                    <input type="text" class="search-input" id="searchInput" placeholder="请输入要分析的内容...">
                    <button class="search-button" id="searchButton">开始</button>
                    <button class="upload-button" id="uploadButton">
                        上传模板
                        <input type="file" id="templateFileInput" accept=".md,.txt" title="上传自定义报告模板(支持 .md 和 .txt 文件)">
                    </button>
                </div>
            </div>
            <div class="upload-status" id="uploadStatus"></div>
        </div>

        <!-- 主内容区域 -->
        <div class="main-content">
            <!-- 嵌入页面区域 -->
            <div class="embedded-section">
                <div class="embedded-header" id="embeddedHeader">嵌入的页面</div>
                <div class="embedded-content" id="embeddedContent">
                    <!-- 论坛聊天界面 -->
                    <div class="forum-container" id="forumContainer">
                        <div class="forum-chat-area" id="forumChatArea">
                            <!-- 动态添加的Engine对话消息将在这里显示 -->
                        </div>
                    </div>
                    
                    <!-- 报告引擎界面 -->
                    <div class="report-container" id="reportContainer">
                        <div class="report-content" id="reportContent">
                            <!-- 报告内容将在这里显示 -->
                        </div>
                    </div>
                    
                    <div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #666;">
                        <span>默认只显示第一个页面 - 点击按钮切换页面</span>
                    </div>
                </div>
            </div>

            <!-- 控制台输出区域 -->
            <div class="console-section">
                <!-- 应用切换按钮 -->
                <div class="app-switcher">
                    <button class="app-button active" data-app="insight">
                        <span class="status-indicator" id="status-insight"></span>
                        Insight Engine
                    </button>
                    <button class="app-button" data-app="media">
                        <span class="status-indicator" id="status-media"></span>
                        Media Engine
                    </button>
                    <button class="app-button" data-app="query">
                        <span class="status-indicator" id="status-query"></span>
                        Query Engine
                    </button>
                    <button class="app-button" data-app="forum">
                        <span class="status-indicator running" id="status-forum"></span>
                        Forum Engine
                    </button>
                    <button class="app-button locked" data-app="report" title="需等待其余三个Agent工作完毕">
                        <span class="status-indicator" id="status-report"></span>
                        Report Engine
                    </button>
                </div>

                <!-- 控制台输出 -->
                <div class="console-output" id="consoleOutput">
                    <div class="console-line">[系统] 等待连接...</div>
                </div>
            </div>
        </div>

        <!-- 状态栏 -->
        <div class="status-bar">
            <span id="connectionStatus">连接中...</span>
            <span id="systemTime"></span>
        </div>
    </div>

    <div class="config-modal-overlay" id="configModal">
        <div class="config-modal">
            <div class="config-modal-header">
                <div class="config-modal-title">LLM 配置 - 与.env文件双向同步</div>
                <div class="config-modal-actions">
                    <button class="config-secondary-button" id="refreshConfigButton">刷新</button>
                    <button class="config-close-button" id="closeConfigModal" aria-label="关闭配置窗口">×</button>
                </div>
            </div>
            <div class="config-modal-body" id="configFormContainer">
                <!-- 由脚本填充 -->
            </div>
            <div class="config-modal-footer">
                <div class="config-status-message" id="configStatusMessage"></div>
                <div class="config-modal-footer-actions">
                    <button class="config-save-button" id="saveConfigButton">保存</button>
                    <button class="config-start-button" id="startSystemButton">保存并启动系统</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 消息提示 -->
    <div class="message" id="message"></div>

    <script>
        // 全局变量
        let socket;
        let currentApp = 'insight';
        let appStatus = {
            insight: 'stopped',
            media: 'stopped',
            query: 'stopped',
            forum: 'stopped',  // 前端启动后再标记为 running
            report: 'stopped'  // Report Engine
        };
        let customTemplate = ''; // 存储用户上传的自定义模板内容
        let configValues = {};
        let configDirty = false;
        let configAutoRefreshTimer = null;
        let systemStarted = false;
        let systemStarting = false;
        let configModalLocked = false;

        const CONFIG_ENDPOINT = '/api/config';
        const SYSTEM_STATUS_ENDPOINT = '/api/system/status';
        const SYSTEM_START_ENDPOINT = '/api/system/start';
        const START_BUTTON_DEFAULT_TEXT = '保存并启动系统';

        const configFieldGroups = [
            {
                title: '数据库连接',
                subtitle: '用于连接业务数据库的基本配置',
                fields: [
                    { key: 'DB_DIALECT', label: '数据库类型', type: 'select', options: ['mysql', 'postgresql'] },
                    { key: 'DB_HOST', label: '主机地址' },
                    { key: 'DB_PORT', label: '端口' },
                    { key: 'DB_USER', label: '用户名' },
                    { key: 'DB_PASSWORD', label: '密码', type: 'password' },
                    { key: 'DB_NAME', label: '数据库名称' },
                    { key: 'DB_CHARSET', label: '字符集' }
                ]
            },
            {
                title: 'Insight Agent',
                subtitle: '负责洞察分析的模型配置',
                fields: [
                    { key: 'INSIGHT_ENGINE_API_KEY', label: 'API Key' },
                    { key: 'INSIGHT_ENGINE_BASE_URL', label: 'Base URL' },
                    { key: 'INSIGHT_ENGINE_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: 'Media Agent',
                subtitle: '媒体内容理解与生成模型',
                fields: [
                    { key: 'MEDIA_ENGINE_API_KEY', label: 'API Key' },
                    { key: 'MEDIA_ENGINE_BASE_URL', label: 'Base URL' },
                    { key: 'MEDIA_ENGINE_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: 'Query Agent',
                subtitle: '负责搜索与信息汇总的模型配置',
                fields: [
                    { key: 'QUERY_ENGINE_API_KEY', label: 'API Key' },
                    { key: 'QUERY_ENGINE_BASE_URL', label: 'Base URL' },
                    { key: 'QUERY_ENGINE_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: 'Report Agent',
                subtitle: '报告生成使用的模型配置',
                fields: [
                    { key: 'REPORT_ENGINE_API_KEY', label: 'API Key' },
                    { key: 'REPORT_ENGINE_BASE_URL', label: 'Base URL' },
                    { key: 'REPORT_ENGINE_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: 'Forum Host',
                subtitle: '多智能体协同使用的模型配置',
                fields: [
                    { key: 'FORUM_HOST_API_KEY', label: 'API Key' },
                    { key: 'FORUM_HOST_BASE_URL', label: 'Base URL' },
                    { key: 'FORUM_HOST_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: 'Keyword Optimizer',
                subtitle: 'SQL / 关键词优化模型配置',
                fields: [
                    { key: 'KEYWORD_OPTIMIZER_API_KEY', label: 'API Key' },
                    { key: 'KEYWORD_OPTIMIZER_BASE_URL', label: 'Base URL' },
                    { key: 'KEYWORD_OPTIMIZER_MODEL_NAME', label: '模型名称' }
                ]
            },
            {
                title: '外部检索工具',
                subtitle: '联动搜索引擎、网站抓取等在线服务',
                fields: [
                    { key: 'TAVILY_API_KEY', label: 'Tavily API Key' },
                    { key: 'BOCHA_WEB_SEARCH_API_KEY', label: 'Bocha API Key' }
                ]
            }
        ];

        // 应用名称映射
        const appNames = {
            insight: 'Insight Engine',
            media: 'Media Engine', 
            query: 'Query Engine',
            forum: 'Forum Engine',
            report: 'Report Engine'
        };

        // 页面头部显示的完整Agent介绍
        const agentTitles = {
            insight: 'Insight Agent - 私有数据库挖掘',
            media: 'Media Agent - 多模态内容分析', 
            query: 'Query Agent - 精准信息搜索',
            forum: 'Forum Engine - 多智能体交流',
            report: 'Report Agent - 最终报告生成'
        };

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initializeSocket();
            initializeEventListeners();
            ensureSystemReadyOnLoad();
            updateTime();
            setInterval(updateTime, 1000);
            checkStatus();
            setInterval(checkStatus, 5000);
            
            // 初始化Report Engine锁定状态检查
            checkReportLockStatus();
            reportLockCheckInterval = setInterval(checkReportLockStatus, 10000); // 每10秒检查一次
            
            // 定期刷新控制台输出
            setInterval(() => {
                refreshConsoleOutput();
            }, 1000);
            
            // 定期刷新论坛对话（实时更新）
            setInterval(() => {
                refreshForumMessages();
            }, 2000);
            
            // 初始化论坛相关功能
            initializeForum();
            
            // 延迟预加载iframe以确保应用启动完成
            setTimeout(() => {
                preloadIframes();
            }, 3000);
        });

        // Socket.IO连接
        function initializeSocket() {
            socket = io();

            socket.on('connect', function() {
                updateConnectionStatus('已连接');
                socket.emit('request_status');
            });

            socket.on('disconnect', function() {
                updateConnectionStatus('连接断开');
            });

            socket.on('console_output', function(data) {
                // 处理控制台输出
                if (data.app === currentApp) {
                    addConsoleOutput(data.line);
                }
                
                // 如果是forum的输出，同时也处理为论坛消息
                if (data.app === 'forum') {
                    const parsed = parseForumMessage(data.line);
                    if (parsed) {
                        // addForumMessage(parsed);
                    }
                }
            });

            socket.on('forum_message', function(data) {
                // addForumMessage(data);
            });

            socket.on('status_update', function(data) {
                updateAppStatus(data);
            });
        }

        // 事件监听器
        function initializeEventListeners() {
            // 搜索按钮
            document.getElementById('searchButton').addEventListener('click', performSearch);
            document.getElementById('searchInput').addEventListener('keypress', function(e) {
                if (e.key === 'Enter') {
                    performSearch();
                }
            });

            // 文件上传
            document.getElementById('templateFileInput').addEventListener('change', handleTemplateUpload);

            // 应用切换按钮
            document.querySelectorAll('.app-button').forEach(button => {
                button.addEventListener('click', function() {
                    const app = this.dataset.app;
                    switchToApp(app);
                });
            });

            // LLM 配置弹窗
            const openConfigButton = document.getElementById('openConfigButton');
            if (openConfigButton) {
                openConfigButton.addEventListener('click', () => openConfigModal({ lock: !systemStarted }));
            }

            const closeConfigButton = document.getElementById('closeConfigModal');
            if (closeConfigButton) {
                closeConfigButton.addEventListener('click', () => closeConfigModal());
            }

            const refreshConfigButton = document.getElementById('refreshConfigButton');
            if (refreshConfigButton) {
                refreshConfigButton.addEventListener('click', () => refreshConfigFromServer(true));
            }

            const saveConfigButton = document.getElementById('saveConfigButton');
            if (saveConfigButton) {
                saveConfigButton.addEventListener('click', () => saveConfigUpdates());
            }

            const startSystemButton = document.getElementById('startSystemButton');
            if (startSystemButton) {
                startSystemButton.addEventListener('click', () => startSystem());
            }

            const configModal = document.getElementById('configModal');
            if (configModal) {
                configModal.addEventListener('click', (event) => {
                    if (event.target === configModal) {
                        closeConfigModal();
                    }
                });
            }

            const configFormContainer = document.getElementById('configFormContainer');
            if (configFormContainer) {
                configFormContainer.addEventListener('input', () => {
                    configDirty = true;
                    setConfigStatus('已修改，尚未保存');
                });
            }

            document.addEventListener('keydown', function(event) {
                if (event.key === 'Escape' && isConfigModalVisible()) {
                    closeConfigModal();
                }
            });
        }

        function isConfigModalVisible() {
            const modal = document.getElementById('configModal');
            return modal ? modal.classList.contains('visible') : false;
        }

        function openConfigModal(options = {}) {
            const { lock = false, message = '' } = options;
            const modal = document.getElementById('configModal');
            if (!modal) {
                return;
            }

            configModalLocked = lock;
            modal.classList.add('visible');
            configDirty = false;

            const initialMessage = message || '正在读取配置...';
            setConfigStatus(initialMessage, '');

            const messageAfterLoad = message || '';

            refreshConfigFromServer(true, messageAfterLoad);

            if (configAutoRefreshTimer) {
                clearInterval(configAutoRefreshTimer);
            }
            configAutoRefreshTimer = setInterval(() => {
                if (!configDirty) {
                    refreshConfigFromServer(false, messageAfterLoad);
                }
            }, 10000);

            updateStartButtonState();
            updateConfigCloseButton();
        }

        function closeConfigModal(force = false) {
            if (!force && configModalLocked && !systemStarted) {
                setConfigStatus('请先完成配置并启动系统', 'error');
                showMessage('请先完成配置并启动系统', 'error');
                return;
            }

            const modal = document.getElementById('configModal');
            if (modal) {
                modal.classList.remove('visible');
            }
            if (configAutoRefreshTimer) {
                clearInterval(configAutoRefreshTimer);
                configAutoRefreshTimer = null;
            }
            configDirty = false;
            configModalLocked = false;
            setConfigStatus('', '');
            updateStartButtonState();
            updateConfigCloseButton();
        }

        function refreshConfigFromServer(showFeedback = false, messageOverride = '') {
            if (showFeedback && configDirty) {
                const proceed = window.confirm('当前修改尚未保存，确定要刷新并放弃更改吗？');
                if (!proceed) {
                    return;
                }
            }
            fetch(CONFIG_ENDPOINT)
                .then(response => response.json())
                .then(data => {
                    if (!data.success) {
                        throw new Error(data.message || '读取配置失败');
                    }
                    configValues = data.config || {};
                    renderConfigForm(configValues);
                    configDirty = false;
                    if (messageOverride) {
                        setConfigStatus(messageOverride);
                    } else if (showFeedback) {
                        setConfigStatus('已加载最新配置');
                    } else {
                        setConfigStatus('已同步最新配置');
                    }
                })
                .catch(error => {
                    console.error(error);
                    setConfigStatus(`读取配置失败: ${error.message}`, 'error');
                });
        }

        function escapeHtml(str) {
            return str.replace(/&/g, '&amp;')
                      .replace(/</g, '&lt;')
                      .replace(/>/g, '&gt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&#39;');
        }

        function renderConfigForm(values) {
            const container = document.getElementById('configFormContainer');
            if (!container) {
                return;
            }

            const sections = configFieldGroups.map(group => {
                const fieldsHtml = group.fields.map(field => {
                    const value = values[field.key] !== undefined ? values[field.key] : '';
                    const safeValue = escapeHtml(String(value || ''));
                    
                    let control;
                    
                    if (field.type === 'select' && field.options) {
                        // 下拉选择框
                        const optionsHtml = field.options.map(option => {
                            const selected = option === value ? 'selected' : '';
                            const safeOption = escapeHtml(String(option));
                            return `<option value="${safeOption}" ${selected}>${safeOption}</option>`;
                        }).join('');
                        control = `
                            <select
                                class="config-field-input"
                                data-config-key="${field.key}"
                                data-field-type="select"
                            >
                                ${optionsHtml}
                            </select>
                        `;
                    } else if (field.type === 'password') {
                        // 密码输入框
                        const inputElement = `
                            <input
                                type="password"
                                class="config-field-input"
                                data-config-key="${field.key}"
                                data-field-type="password"
                                value="${safeValue}"
                                placeholder="填写${field.label}"
                                autocomplete="off"
                            >
                        `;
                        control = `
                            <div class="config-password-wrapper">
                                ${inputElement}
                                <button type="button" class="config-password-toggle" data-target="${field.key}">显示</button>
                            </div>
                        `;
                    } else {
                        // 普通文本输入框
                        const inputType = field.type || 'text';
                        control = `
                            <input
                                type="${inputType}"
                                class="config-field-input"
                                data-config-key="${field.key}"
                                data-field-type="${inputType}"
                                value="${safeValue}"
                                placeholder="填写${field.label}"
                                autocomplete="on"
                            >
                        `;
                    }

                    return `
                        <label class="config-field">
                            <span class="config-field-label">${field.label}</span>
                            ${control}
                        </label>
                    `;
                }).join('');

                const subtitle = group.subtitle ? `<div class="config-group-subtitle">${group.subtitle}</div>` : '';

                return `
                    <section class="config-group">
                        <div class="config-group-title">${group.title}</div>
                        ${subtitle}
                        ${fieldsHtml}
                    </section>
                `;
            }).join('');

            container.innerHTML = sections;
            attachConfigPasswordToggles();
        }

        function attachConfigPasswordToggles() {
            const toggles = document.querySelectorAll('.config-password-toggle');
            toggles.forEach(toggle => {
                const key = toggle.dataset.target;
                const input = document.querySelector(`.config-field-input[data-config-key="${key}"]`);
                if (!input) {
                    return;
                }
                toggle.addEventListener('click', () => {
                    const reveal = input.getAttribute('type') === 'password';
                    input.setAttribute('type', reveal ? 'text' : 'password');
                    toggle.textContent = reveal ? '隐藏' : '显示';
                    toggle.classList.toggle('revealed', reveal);
                });
            });
        }

        function collectConfigUpdates() {
            const inputs = document.querySelectorAll('#configFormContainer [data-config-key]');
            const updates = {};
            inputs.forEach(input => {
                const key = input.dataset.configKey;
                if (!key) {
                    return;
                }
                const fieldType = input.dataset.fieldType || 'text';
                let value = input.value;
                if (fieldType !== 'password' && typeof value === 'string') {
                    value = value.trim();
                }

                if (value !== '' && /PORT$/i.test(key)) {
                    const numeric = Number(value);
                    if (!Number.isNaN(numeric)) {
                        updates[key] = numeric;
                        return;
                    }
                }

                updates[key] = value;
            });
            return updates;
        }

        function setConfigStatus(message, type = '') {
            const status = document.getElementById('configStatusMessage');
            if (!status) {
                return;
            }
            status.textContent = message || '';
            status.classList.remove('error', 'success');
            if (type) {
                status.classList.add(type);
            }
        }

        async function saveConfigUpdates(options = {}) {
            const { silent = false } = options;
            const saveButton = document.getElementById('saveConfigButton');

            if (!silent && saveButton) {
                saveButton.disabled = true;
                saveButton.textContent = '保存中...';
            }
            if (!silent) {
                setConfigStatus('正在保存配置...', '');
            }

            const updates = collectConfigUpdates();

            try {
                const response = await fetch(CONFIG_ENDPOINT, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(updates)
                });
                const data = await response.json();
                if (!data.success) {
                    throw new Error(data.message || '保存失败');
                }
                configValues = data.config || {};
                renderConfigForm(configValues);
                configDirty = false;
                if (silent) {
                    setConfigStatus('配置已保存', 'success');
                } else {
                    setConfigStatus('配置已保存', 'success');
                    showMessage('配置已保存', 'success');
                }
                return true;
            } catch (error) {
                console.error(error);
                setConfigStatus(`保存失败: ${error.message}`, 'error');
                if (!silent) {
                    showMessage(`保存失败: ${error.message}`, 'error');
                }
                return false;
            } finally {
                if (!silent && saveButton) {
                    saveButton.disabled = false;
                    saveButton.textContent = '保存';
                }
            }
        }

        function updateStartButtonState() {
            const startButton = document.getElementById('startSystemButton');
            if (!startButton) {
                return;
            }

            if (systemStarting) {
                startButton.disabled = true;
                startButton.textContent = '启动中...';
            } else if (systemStarted) {
                startButton.disabled = true;
                startButton.textContent = '系统已启动';
            } else {
                startButton.disabled = false;
                startButton.textContent = START_BUTTON_DEFAULT_TEXT;
            }
        }

        function updateConfigCloseButton() {
            const closeButton = document.getElementById('closeConfigModal');
            if (!closeButton) {
                return;
            }
            if (configModalLocked && !systemStarted) {
                closeButton.setAttribute('disabled', 'disabled');
            } else {
                closeButton.removeAttribute('disabled');
            }
        }

        function applySystemState(state) {
            if (!state) {
                return;
            }
            if (Object.prototype.hasOwnProperty.call(state, 'started')) {
                systemStarted = !!state.started;
            }
            if (Object.prototype.hasOwnProperty.call(state, 'starting')) {
                systemStarting = !!state.starting;
            }
            updateStartButtonState();
            updateConfigCloseButton();
        }

        async function fetchSystemStatus() {
            try {
                const response = await fetch(SYSTEM_STATUS_ENDPOINT);
                const data = await response.json();
                if (data && data.success) {
                    applySystemState(data);
                }
                return data;
            } catch (error) {
                console.error('获取系统状态失败', error);
                return null;
            }
        }

        async function ensureSystemReadyOnLoad() {
            const status = await fetchSystemStatus();
            if (!status || !status.success) {
                openConfigModal({
                    lock: true,
                    message: '无法获取系统状态，请检查配置后重试。'
                });
                return;
            }

            if (!status.started) {
                openConfigModal({
                    lock: true,
                    message: '请先确认配置，然后点击“保存并启动系统”'
                });
            } else {
                applySystemState(status);
                configModalLocked = false;
            }
        }

        async function startSystem() {
            if (systemStarting) {
                setConfigStatus('系统正在启动，请稍候...', '');
                return;
            }

            systemStarting = true;
            updateStartButtonState();

            try {
                if (configDirty) {
                    setConfigStatus('检测到未保存的修改，正在保存配置...', '');
                    const saved = await saveConfigUpdates({ silent: true });
                    if (!saved) {
                        systemStarting = false;
                        updateStartButtonState();
                        return;
                    }
                }

                setConfigStatus('正在启动系统...', '');
                const response = await fetch(SYSTEM_START_ENDPOINT, { method: 'POST' });
                const data = await response.json();
                if (!response.ok || !data.success) {
                    const message = data && data.message ? data.message : '系统启动失败';
                    throw new Error(message);
                }

                showMessage('系统启动成功', 'success');
                setConfigStatus('系统启动成功', 'success');
                applySystemState({ started: true, starting: false });
                configModalLocked = false;

                setTimeout(() => {
                    closeConfigModal();
                }, 800);

                setTimeout(() => {
                    checkStatus();
                }, 1000);

                setTimeout(() => {
                    window.location.reload();
                }, 1200);
            } catch (error) {
                setConfigStatus(`系统启动失败: ${error.message}`, 'error');
                showMessage(`系统启动失败: ${error.message}`, 'error');
                applySystemState({ started: false, starting: false });
            } finally {
                systemStarting = false;
                updateStartButtonState();
                await fetchSystemStatus();
            }
        }

        // 执行搜索
        function performSearch() {
            const query = document.getElementById('searchInput').value.trim();
            if (!query) {
                showMessage('请输入搜索内容', 'error');
                return;
            }

            const button = document.getElementById('searchButton');
            button.disabled = true;
            button.innerHTML = '<span class="loading"></span> 搜索中...';

            // 清除现有报告，重置自动生成标志，为新搜索做准备
            const reportPreview = document.getElementById('reportPreview');
            if (reportPreview) {
                reportPreview.innerHTML = '<div class="report-loading">等待新的搜索结果生成报告...</div>';
            }
            
            // 清除任务进度显示
            const taskProgressArea = document.getElementById('taskProgressArea');
            if (taskProgressArea) {
                taskProgressArea.innerHTML = '';
            }
            
            // 重置自动生成相关标志
            autoGenerateTriggered = false;
            reportTaskId = null;
            
            // 停止可能正在进行的轮询
            if (reportPollingInterval) {
                clearInterval(reportPollingInterval);
                reportPollingInterval = null;
            }

            // 确保所有iframe已初始化
            if (!iframesInitialized) {
                preloadIframes();
            }
            
            // 向所有运行中的应用发送搜索请求（通过刷新iframe传递参数）
            let totalRunning = 0;
            const ports = { insight: 8501, media: 8502, query: 8503 };
            
            Object.keys(appStatus).forEach(app => {
                if (appStatus[app] === 'running' && preloadedIframes[app]) {
                    totalRunning++;
                    
                    // 构建搜索URL
                    const searchUrl = `http://${window.location.hostname}:${ports[app]}?query=${encodeURIComponent(query)}&auto_search=true`;
                    console.log(`向 ${app} 发送搜索请求: ${searchUrl}`);
                    
                    // 直接更新主iframe的src来传递搜索参数
                    preloadedIframes[app].src = searchUrl;
                }
            });
            
            if (totalRunning === 0) {
                button.disabled = false;
                button.innerHTML = '搜索';
                showMessage('没有运行中的应用，无法执行搜索', 'error');
            } else {
                button.disabled = false;
                button.innerHTML = '搜索';
                showMessage(`搜索请求已发送到 ${totalRunning} 个应用，页面将刷新以开始研究`, 'success');
            }
        }

        // 切换应用
        function switchToApp(app) {
            if (app === currentApp) return;

            // 检查Report Engine是否被锁定
            if (app === 'report') {
                const reportButton = document.querySelector(`[data-app="report"]`);
                if (reportButton.classList.contains('locked')) {
                    showMessage('需等待其余三个Agent工作完毕', 'error');
                    return;
                }
            }

            // 更新按钮状态
            document.querySelectorAll('.app-button').forEach(btn => {
                btn.classList.remove('active');
            });
            document.querySelector(`[data-app="${app}"]`).classList.add('active');

            currentApp = app;

            // 根据应用类型处理不同的显示逻辑
            if (app === 'forum') {
                // 切换到论坛模式
                document.getElementById('embeddedHeader').textContent = 'Forum Engine - 多智能体交流';
                
                // 显示论坛容器，隐藏其他内容
                document.getElementById('forumContainer').classList.add('active');
                document.getElementById('reportContainer').classList.remove('active');
                
                // 清空控制台并加载forum日志
                document.getElementById('consoleOutput').innerHTML = '<div class="console-line">[系统] 切换到论坛模式</div>';
                loadForumLog();
                
            } else if (app === 'report') {
                // 切换到报告模式
                document.getElementById('embeddedHeader').textContent = 'Report Agent - 最终报告生成';
                
                // 显示报告容器，隐藏其他内容
                document.getElementById('reportContainer').classList.add('active');
                document.getElementById('forumContainer').classList.remove('active');
                
                // 清空控制台并加载report日志
                document.getElementById('consoleOutput').innerHTML = '<div class="console-line">[系统] 切换到报告生成模式</div>';
                loadReportLog();
                
                // 只在报告界面未初始化时才重新加载
                const reportContent = document.getElementById('reportContent');
                if (!reportContent || reportContent.children.length === 0) {
                    loadReportInterface();
                }
                
                // 切换到report页面时检查是否可以自动生成报告
                setTimeout(() => {
                    checkReportLockStatus();
                }, 500);
                
            } else {
                // 切换到普通Engine模式
                document.getElementById('embeddedHeader').textContent = agentTitles[app] || appNames[app];
                
                // 隐藏论坛和报告容器
                document.getElementById('forumContainer').classList.remove('active');
                document.getElementById('reportContainer').classList.remove('active');
                
                // 清空并加载新的控制台输出
                document.getElementById('consoleOutput').innerHTML = '<div class="console-line">[系统] 切换到 ' + appNames[app] + '</div>';
                
                // 重置行计数
                lastLineCount[app] = 0;
                loadConsoleOutput(app);
            }

            // 更新嵌入页面
            updateEmbeddedPage(app);
        }

        // 存储最后显示的行数，避免重复加载
        let lastLineCount = {};
        
        // 加载控制台输出
        function loadConsoleOutput(app) {
            if (app === 'forum') {
                loadForumLog();
                return;
            }
            
            if (app === 'report') {
                loadReportLog();
                return;
            }
            
            fetch(`/api/output/${app}`)
            .then(response => response.json())
            .then(data => {
                if (data.success && data.output.length > 0) {
                    const consoleOutput = document.getElementById('consoleOutput');
                    
                    // 只添加新的行
                    const lastCount = lastLineCount[app] || 0;
                    const newLines = data.output.slice(lastCount);
                    
                    newLines.forEach(line => {
                        const div = document.createElement('div');
                        div.className = 'console-line';
                        div.textContent = line;
                        consoleOutput.appendChild(div);
                    });
                    
                    lastLineCount[app] = data.output.length;
                    consoleOutput.scrollTop = consoleOutput.scrollHeight;
                }
            })
            .catch(error => {
                console.error('加载输出失败:', error);
            });
        }
        
        // 刷新当前应用的控制台输出
        function refreshConsoleOutput() {
            if (currentApp === 'forum') {
                refreshForumLog();
                return;
            }
            
            if (currentApp === 'report') {
                refreshReportLog();
                return;
            }
            
            if (appStatus[currentApp] === 'running' || appStatus[currentApp] === 'starting') {
                fetch(`/api/output/${currentApp}`)
                .then(response => response.json())
                .then(data => {
                    if (data.success && data.output.length > 0) {
                        const consoleOutput = document.getElementById('consoleOutput');
                        
                        // 只添加新的行
                        const lastCount = lastLineCount[currentApp] || 0;
                        const newLines = data.output.slice(lastCount);
                        
                        if (newLines.length > 0) {
                            newLines.forEach(line => {
                                const div = document.createElement('div');
                                div.className = 'console-line';
                                div.textContent = line;
                                consoleOutput.appendChild(div);
                            });
                            
                            lastLineCount[currentApp] = data.output.length;
                            consoleOutput.scrollTop = consoleOutput.scrollHeight;
                        }
                    }
                })
                .catch(error => {
                    console.error('刷新输出失败:', error);
                });
            }
        }

        // 添加控制台输出
        function addConsoleOutput(line) {
            const consoleOutput = document.getElementById('consoleOutput');
            const div = document.createElement('div');
            div.className = 'console-line';
            div.textContent = line;
            consoleOutput.appendChild(div);

            // 自动滚动到底部显示最新内容
            consoleOutput.scrollTop = consoleOutput.scrollHeight;
        }

        // 预加载的iframe存储
        let preloadedIframes = {};
        let iframesInitialized = false;
        
        // 预加载所有iframe（只执行一次）
        function preloadIframes() {
            if (iframesInitialized) return;
            
            const ports = { insight: 8501, media: 8502, query: 8503 };
            const content = document.getElementById('embeddedContent');
            
            for (const [app, port] of Object.entries(ports)) {
                const iframe = document.createElement('iframe');
                iframe.src = `http://${window.location.hostname}:${port}`;
                iframe.style.width = '100%';
                iframe.style.height = '100%';
                iframe.style.border = 'none';
                iframe.style.position = 'absolute';
                iframe.style.top = '0';
                iframe.style.left = '0';
                iframe.style.display = 'none';
                iframe.id = `iframe-${app}`;
                
                // 直接添加到content区域
                content.appendChild(iframe);
                preloadedIframes[app] = iframe;
                
                console.log(`预加载 ${app} 应用完成`);
            }
            
            iframesInitialized = true;
            console.log('所有iframe预加载完成，准备进行无缝切换');
        }

        // 更新嵌入页面
        function updateEmbeddedPage(app) {
            const header = document.getElementById('embeddedHeader');
            const content = document.getElementById('embeddedContent');
            
            // 如果是Forum Engine，直接显示论坛界面
            if (app === 'forum') {
                header.textContent = 'Forum Engine - 多智能体交流';
                
                // 隐藏所有iframe
                if (typeof preloadedIframes !== 'undefined') {
                    Object.values(preloadedIframes).forEach(iframe => {
                        iframe.style.display = 'none';
                    });
                }
                
                // 移除占位符
                const placeholder = content.querySelector('.status-placeholder');
                if (placeholder) {
                    placeholder.remove();
                }
                
                // 显示论坛容器，隐藏报告容器
                document.getElementById('forumContainer').classList.add('active');
                document.getElementById('reportContainer').classList.remove('active');
                return;
            }
            
            // 如果是Report Engine，显示报告界面
            if (app === 'report') {
                header.textContent = 'Report Agent - 最终报告生成';
                
                // 隐藏所有iframe
                if (typeof preloadedIframes !== 'undefined') {
                    Object.values(preloadedIframes).forEach(iframe => {
                        iframe.style.display = 'none';
                    });
                }
                
                // 移除占位符
                const placeholder = content.querySelector('.status-placeholder');
                if (placeholder) {
                    placeholder.remove();
                }
                
                // 显示报告容器，隐藏论坛容器
                document.getElementById('reportContainer').classList.add('active');
                document.getElementById('forumContainer').classList.remove('active');
                return;
            }
            
            // 隐藏论坛和报告容器
            document.getElementById('forumContainer').classList.remove('active');
            document.getElementById('reportContainer').classList.remove('active');

            header.textContent = agentTitles[app] || appNames[app] || app;

            // 如果应用正在运行，显示对应的iframe
            if (appStatus[app] === 'running') {
                // 确保iframe已初始化
                if (!iframesInitialized) {
                    preloadIframes();
                }
                
                // 隐藏所有iframe
                Object.values(preloadedIframes).forEach(iframe => {
                    iframe.style.display = 'none';
                });
                
                // 移除占位符
                const placeholder = content.querySelector('.status-placeholder');
                if (placeholder) {
                    placeholder.remove();
                }
                
                // 显示当前应用的iframe
                if (preloadedIframes[app]) {
                    preloadedIframes[app].style.display = 'block';
                    console.log(`切换到 ${app} 应用 - 无刷新切换`);
                }
            } else {
                // 隐藏所有iframe
                Object.values(preloadedIframes).forEach(iframe => {
                    iframe.style.display = 'none';
                });
                
                // 显示状态信息
                let placeholder = content.querySelector('.status-placeholder');
                if (!placeholder) {
                    placeholder = document.createElement('div');
                    placeholder.className = 'status-placeholder';
                    placeholder.style.cssText = 'display: flex; align-items: center; justify-content: center; height: 100%; color: #666; flex-direction: column; position: absolute; top: 0; left: 0; width: 100%;';
                    content.appendChild(placeholder);
                }
                
                placeholder.innerHTML = `
                    <div style="margin-bottom: 10px;">${appNames[app]} 未运行</div>
                    <div style="font-size: 12px;">状态: ${appStatus[app]}</div>
                `;
            }
        }

        // 检查应用状态
        function checkStatus() {
            fetch('/api/status')
            .then(response => response.json())
            .then(data => {
                updateAppStatus(data);
            })
            .catch(error => {
                console.error('状态检查失败:', error);
            });
        }

        // 更新应用状态
        function updateAppStatus(data) {
            for (const [app, info] of Object.entries(data)) {
                // 适配实际的API格式：{app: {status: string, port: int, output_lines: int}}
                const status = info.status === 'running' ? 'running' : 'stopped';
                appStatus[app] = status;
                
                const indicator = document.getElementById(`status-${app}`);
                if (indicator) {
                    indicator.className = `status-indicator ${status}`;
                }
            }

            // 如果当前显示的应用状态发生变化，更新嵌入页面
            updateEmbeddedPage(currentApp);
        }

        // 更新连接状态
        function updateConnectionStatus(status) {
            document.getElementById('connectionStatus').textContent = status;
        }

        // 更新时间
        function updateTime() {
            const now = new Date();
            const timeString = now.toLocaleTimeString('zh-CN');
            document.getElementById('systemTime').textContent = timeString;
        }

        // 显示消息
        function showMessage(text, type = 'info') {
            const message = document.getElementById('message');
            
            // 清除之前的定时器
            if (message.hideTimer) {
                clearTimeout(message.hideTimer);
            }
            
            message.textContent = text;
            message.className = `message ${type}`;
            message.classList.add('show');

            message.hideTimer = setTimeout(() => {
                message.classList.remove('show');
                // 延迟清除内容，等待动画完成
                setTimeout(() => {
                    message.textContent = '';
                    message.className = 'message';
                }, 300);
            }, 3000);
        }

        // 处理模板文件上传
        function handleTemplateUpload(event) {
            const file = event.target.files[0];
            const statusDiv = document.getElementById('uploadStatus');
            
            if (!file) {
                statusDiv.textContent = '';
                statusDiv.className = 'upload-status';
                customTemplate = '';
                return;
            }

            // 检查文件类型
            const allowedTypes = ['text/markdown', 'text/plain', '.md', '.txt'];
            const fileName = file.name.toLowerCase();
            const isValidType = fileName.endsWith('.md') || fileName.endsWith('.txt') || 
                              allowedTypes.includes(file.type);

            if (!isValidType) {
                statusDiv.textContent = '错误: 请选择 .md 或 .txt 文件';
                statusDiv.className = 'upload-status error';
                customTemplate = '';
                event.target.value = ''; // 清空文件输入
                return;
            }

            // 检查文件大小 (最大 1MB)
            const maxSize = 1024 * 1024; // 1MB
            if (file.size > maxSize) {
                statusDiv.textContent = '错误: 文件大小不能超过 1MB';
                statusDiv.className = 'upload-status error';
                customTemplate = '';
                event.target.value = '';
                return;
            }

            statusDiv.textContent = '正在读取文件...';
            statusDiv.className = 'upload-status';

            // 读取文件内容
            const reader = new FileReader();
            reader.onload = function(e) {
                try {
                    customTemplate = e.target.result;
                    statusDiv.textContent = `成功: 已加载自定义模板 "${file.name}" (${(file.size/1024).toFixed(1)}KB)`;
                    statusDiv.className = 'upload-status success';
                    showMessage(`自定义模板已加载: ${file.name}`, 'success');
                } catch (error) {
                    statusDiv.textContent = '错误: 文件读取失败';
                    statusDiv.className = 'upload-status error';
                    customTemplate = '';
                    event.target.value = '';
                }
            };

            reader.onerror = function() {
                statusDiv.textContent = '错误: 文件读取失败';
                statusDiv.className = 'upload-status error';
                customTemplate = '';
                event.target.value = '';
            };

            reader.readAsText(file, 'utf-8');
        }

        // Forum Engine 相关函数
        let forumLogLineCount = 0;
        
        // Report Engine 相关函数
        let reportLogLineCount = 0;
        let reportLockCheckInterval = null;

        // 实时刷新论坛消息（适用于所有页面）
        function refreshForumMessages() {
            fetch('/api/forum/log')
            .then(response => response.json())
            .then(data => {
                if (data.success && data.log_lines.length > forumLogLineCount) {
                    console.log(`Forum: 发现新消息，当前行数: ${data.log_lines.length}, 上次处理: ${forumLogLineCount}`);
                    
                    // 只处理新增的日志行
                    const newLines = data.log_lines.slice(forumLogLineCount);
                    newLines.forEach((line, index) => {
                        console.log(`Forum: 处理新行 ${forumLogLineCount + index + 1}: ${line}`);
                        const parsed = parseForumMessage(line);
                        if (parsed) {
                            console.log(`Forum: 解析成功，添加消息:`, parsed);
                            addForumMessage(parsed);
                        }
                    });
                    forumLogLineCount = data.log_lines.length;
                }
            })
            .catch(error => {
                console.error('刷新论坛消息失败:', error);
            });
        }

        // 初始化论坛功能
        function initializeForum() {
            // 初始化时加载一次论坛日志
            refreshForumMessages();
        }

        // 加载论坛日志
        function loadForumLog() {
            fetch('/api/forum/log')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 清空对话区
                    const chatArea = document.getElementById('forumChatArea');
                    chatArea.innerHTML += `
                        <div class="forum-message system">
                            <div class="forum-message-header">SYSTEM</div>
                            <div class="forum-message-content">ForumEngine 论坛已启动，ID：98fiaw4324dwadhsl21awhs908147</div>
                            <div class="forum-timestamp">${new Date().toLocaleTimeString('zh-CN')}</div>
                        </div>
                    `;
                    
                    // 加载控制台日志
                    const consoleOutput = document.getElementById('consoleOutput');
                    consoleOutput.innerHTML = '<div class="console-line">[系统] Forum Engine 日志输出</div>';
                    
                    if (data.log_lines && data.log_lines.length > 0) {
                        data.log_lines.forEach(line => {
                            const div = document.createElement('div');
                            div.className = 'console-line';
                            div.textContent = line;
                            consoleOutput.appendChild(div);
                            
                            // 解析并添加到对话区
                            const parsed = parseForumMessage(line);
                            //if (parsed) {
                                //addForumMessage(parsed);
                            //}
                        });
                        
                        // 重置计数器以确保后续消息能正确显示
                        forumLogLineCount = data.log_lines.length;
                    } else {
                        // 如果没有日志，重置计数器
                        forumLogLineCount = 0;
                    }
                    
                    // 如果有解析的消息，直接使用
                    if (data.parsed_messages && data.parsed_messages.length > 0) {
                        data.parsed_messages.forEach(message => {
                            // addForumMessage(message);
                        });
                    }
                    
                    consoleOutput.scrollTop = consoleOutput.scrollHeight;
                }
            })
            .catch(error => {
                console.error('加载论坛日志失败:', error);
            });
        }

        // 刷新论坛日志
        function refreshForumLog() {
            fetch('/api/forum/log')
            .then(response => response.json())
            .then(data => {
                if (data.success && data.log_lines.length > forumLogLineCount) {
                    const consoleOutput = document.getElementById('consoleOutput');
                    
                    // 只添加新的行
                    const newLines = data.log_lines.slice(forumLogLineCount);
                    newLines.forEach(line => {
                        const div = document.createElement('div');
                        div.className = 'console-line';
                        div.textContent = line;
                        consoleOutput.appendChild(div);
                        
                        // 如果是论坛对话内容，也显示到左侧对话区
                        const parsed = parseForumMessage(line);
                        if (parsed) {
                            addForumMessage(parsed);
                        }
                    });
                    
                    forumLogLineCount = data.log_lines.length;
                    consoleOutput.scrollTop = consoleOutput.scrollHeight;
                }
            })
            .catch(error => {
                console.error('刷新论坛日志失败:', error);
            });
        }

        // 刷新Report Engine日志
        // 检查Report Engine锁定状态并自动生成报告
        let autoGenerateTriggered = false; // 防止重复触发
        
        function checkReportLockStatus() {
            fetch('/api/report/status')
            .then(response => response.json())
            .then(data => {
                const reportButton = document.querySelector('[data-app="report"]');
                
                if (data.success && data.engines_ready) {
                    // 文件准备就绪，解锁按钮
                    reportButton.classList.remove('locked');
                    reportButton.title = 'Report Engine - 智能报告生成\n所有引擎都有新文件，可以生成报告';
                    
                    // 检查是否已经有报告在显示
                    const reportPreview = document.getElementById('reportPreview');
                    const hasReport = reportPreview && reportPreview.querySelector('iframe');
                    
                    // 如果当前在report页面且还没有触发自动生成且没有正在进行的任务且没有已显示的报告，则自动生成报告
                    if (currentApp === 'report' && !autoGenerateTriggered && !reportTaskId && !hasReport) {
                        autoGenerateTriggered = true;
                        console.log('检测到锁消失且无现有报告，自动开始生成报告');
                        setTimeout(() => {
                            generateReport();
                        }, 1000); // 延迟1秒开始生成
                    }
                } else {
                    // 文件未准备就绪，锁定按钮
                    reportButton.classList.add('locked');
                    
                    // 构建详细的提示信息
                    let titleInfo = '\n';
                    
                    if (data.missing_files && data.missing_files.length > 0) {
                        titleInfo += '等待新文件:\n' + data.missing_files.join('\n');
                    } else {
                        titleInfo += '等待三个Agent工作完毕';
                    }
                    
                    reportButton.title = titleInfo;
                }
            })
            .catch(error => {
                console.error('检查Report Engine状态失败:', error);
                // 出错时默认锁定
                const reportButton = document.querySelector('[data-app="report"]');
                reportButton.classList.add('locked');
                reportButton.title = 'Report Engine状态检查失败';
            });
        }

        function refreshReportLog() {
            fetch('/api/report/log')
            .then(response => response.json())
            .then(data => {
                if (data.success && data.log_lines.length > reportLogLineCount) {
                    const consoleOutput = document.getElementById('consoleOutput');
                    
                    // 只添加新的行
                    const newLines = data.log_lines.slice(reportLogLineCount);
                    newLines.forEach(line => {
                        const div = document.createElement('div');
                        div.className = 'console-line';
                        div.textContent = line;
                        consoleOutput.appendChild(div);
                    });
                    
                    reportLogLineCount = data.log_lines.length;
                    consoleOutput.scrollTop = consoleOutput.scrollHeight;
                }
            })
            .catch(error => {
                console.error('刷新Report日志失败:', error);
            });
        }

        // 加载Report Engine日志
        function loadReportLog() {
            fetch('/api/report/log')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const consoleOutput = document.getElementById('consoleOutput');
                    consoleOutput.innerHTML = '<div class="console-line">[系统] Report Engine 日志监控已启动</div>';
                    
                    if (data.log_lines && data.log_lines.length > 0) {
                        data.log_lines.forEach(line => {
                            const div = document.createElement('div');
                            div.className = 'console-line';
                            div.textContent = line;
                            consoleOutput.appendChild(div);
                        });
                        
                        // 重置计数器以确保后续消息能正确显示
                        reportLogLineCount = data.log_lines.length;
                    } else {
                        // 如果没有日志，重置计数器
                        reportLogLineCount = 0;
                    }
                    
                    consoleOutput.scrollTop = consoleOutput.scrollHeight;
                }
            })
            .catch(error => {
                console.error('加载Report日志失败:', error);
            });
        }

        // 解析论坛消息并添加到对话区
        function parseForumMessage(logLine) {
            try {
                // 解析日志行格式: [HH:MM:SS] [SOURCE] content
                const timeMatch = logLine.match(/^\[(\d{2}:\d{2}:\d{2})\]/);
                if (!timeMatch) return null;
                
                const timestamp = timeMatch[1];
                const restContent = logLine.substring(timeMatch[0].length).trim();
                
                // 解析源标签
                const sourceMatch = restContent.match(/^\[([^\]]+)\]\s*(.*)$/);
                if (!sourceMatch) return null;
                
                const source = sourceMatch[1];
                const content = sourceMatch[2];
                
                // 处理四种消息类型：三个Engine和HOST，过滤掉系统消息和空内容
                if (!['QUERY', 'INSIGHT', 'MEDIA', 'HOST'].includes(source.toUpperCase()) || 
                    !content || content.includes('=== ForumEngine')) {
                    return null;
                }
                
                // 根据源类型确定消息类型
                let messageType = 'agent';
                let displayName = '';
                
                switch(source.toUpperCase()) {
                    case 'INSIGHT':
                        displayName = 'Insight Engine';
                        break;
                    case 'MEDIA':
                        displayName = 'Media Engine';
                        break;
                    case 'QUERY':
                        displayName = 'Query Engine';
                        break;
                    case 'HOST':
                        messageType = 'host';
                        displayName = 'Forum Host';
                        break;
                }
                
                // 处理内容中的转义字符
                const displayContent = content.replace(/\\n/g, '\n').replace(/\\r/g, '');
                
                // 返回解析后的消息对象
                return {
                    type: messageType,
                    source: displayName,
                    content: displayContent,
                    timestamp: timestamp
                };
                
            } catch (error) {
                console.error('解析论坛消息失败:', error);
                return null;
            }
        }

        // 添加论坛消息到对话区
        function addForumMessage(data) {
            const chatArea = document.getElementById('forumChatArea');
            const messageDiv = document.createElement('div');
            
            const messageType = data.type || 'system';
            messageDiv.className = `forum-message ${messageType}`;
            
            // 根据来源添加特定的CSS类用于颜色区分
            if (data.source) {
                const sourceClass = data.source.toLowerCase().replace(/\s+/g, '-');
                messageDiv.classList.add(sourceClass);
                
                // 添加具体的engine类
                if (data.source.toLowerCase().includes('query')) {
                    messageDiv.classList.add('query-engine');
                } else if (data.source.toLowerCase().includes('insight')) {
                    messageDiv.classList.add('insight-engine');
                } else if (data.source.toLowerCase().includes('media')) {
                    messageDiv.classList.add('media-engine');
                } else if (data.source.toLowerCase().includes('host')) {
                    messageDiv.classList.add('host');
                }
            }
            
            // 构建消息头部，显示来源名称
            const headerText = data.sender || data.source || getMessageHeader(messageType);
            
            messageDiv.innerHTML = `
                <div class="forum-message-header">${headerText}</div>
                <div class="forum-message-content">${formatMessageContent(data.content)}</div>
                <div class="forum-timestamp">${data.timestamp || new Date().toLocaleTimeString('zh-CN')}</div>
            `;
            
            chatArea.appendChild(messageDiv);
            
            // 自动滚动到底部
            chatArea.scrollTop = chatArea.scrollHeight;
        }

        // 格式化消息内容
        function formatMessageContent(content) {
            if (!content) return '';
            
            // 将换行符转换为HTML换行
            return content.replace(/\n/g, '<br>');
        }

        // 获取消息头部
        function getMessageHeader(type) {
            switch(type) {
                case 'user': return '用户';
                case 'agent': return 'AI助手';
                case 'system': return '系统';
                case 'host': return '论坛主持人';
                default: return '未知';
            }
        }

        // Report Engine 相关函数
        let reportTaskId = null;
        let reportPollingInterval = null;

        // 加载报告界面
        function loadReportInterface() {
            const reportContent = document.getElementById('reportContent');
            
            // 检查ReportEngine状态
            fetch('/api/report/status')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 更新ReportEngine状态指示器
                    const indicator = document.getElementById('status-report');
                    if (indicator) {
                        if (data.initialized) {
                            indicator.className = 'status-indicator running';
                            appStatus.report = 'running';
                        } else {
                            indicator.className = 'status-indicator';
                            appStatus.report = 'stopped';
                        }
                    }
                    
                    // 渲染报告界面
                    renderReportInterface(data);
                } else {
                    reportContent.innerHTML = `
                        <div class="report-status error">
                            <strong>错误:</strong> ${data.error}
                        </div>
                    `;
                }
            })
            .catch(error => {
                console.error('加载报告界面失败:', error);
                reportContent.innerHTML = `
                    <div class="report-status error">
                        <strong>加载失败:</strong> ${error.message}
                    </div>
                `;
            });
        }

        // 渲染报告界面
        function renderReportInterface(statusData) {
            const reportContent = document.getElementById('reportContent');
            
            let interfaceHTML = `
                <!-- 固定的状态信息块 -->
                <div class="engine-status-info" id="engineStatusBlock">
                    <div class="report-status" id="engineStatusContent">
                        <div>正在初始化...</div>
                    </div>
                </div>
                
                <!-- 任务进度区域 -->
                <div id="taskProgressArea"></div>
                
                <!-- 报告预览区域 -->
                <div class="report-preview" id="reportPreview">
                    <div class="report-loading">
                        点击"生成最终报告"开始生成综合分析报告
                    </div>
                </div>
            `;
            
            reportContent.innerHTML = interfaceHTML;
            
            // 立即更新状态信息
            updateEngineStatusDisplay(statusData);
            
            // 如果有当前任务，显示任务状态
            if (statusData.current_task) {
                const taskArea = document.getElementById('taskProgressArea');
                if (taskArea) {
                    taskArea.innerHTML = renderTaskStatus(statusData.current_task);
                }
            }
        }

        // 渲染任务状态（使用新的进度条样式）
        function renderTaskStatus(task) {
            // 状态文本的中文映射
            const statusText = {
                'running': '正在生成',
                'completed': '已完成',
                'error': '生成失败',
                'pending': '等待中'
            };
            
            // 状态徽章样式
            const statusBadgeClass = {
                'running': 'task-status-running',
                'completed': 'task-status-completed',
                'error': 'task-status-error',
                'pending': 'task-status-running'
            };
            
            // 为运行状态添加加载指示器
            const loadingIndicator = task.status !== 'completed' && task.status !== 'error' 
                ? '<span class="report-loading-spinner"></span>' 
                : '';
            
            let statusHTML = `
                <div class="task-progress-container">
                    <div class="task-progress-header">
                        <div class="task-progress-title">
                            ${loadingIndicator}报告生成任务
                        </div>
                        <div class="task-progress-bar">
                            <div class="task-progress-fill" style="width: ${Math.min(Math.max(task.progress || 0, 0), 100)}%"></div>
                            <div class="task-progress-text">${task.progress || 0}%</div>
                        </div>
                    </div>
                    
                    <div class="task-info-line">
                        <div class="task-info-item">
                            <span class="task-info-label">任务ID:</span>
                            <span class="task-info-value">${task.task_id}</span>
                        </div>
                        <div class="task-info-item">
                            <span class="task-info-label">查询内容:</span>
                            <span class="task-info-value">${task.query}</span>
                        </div>
                        <div class="task-info-item">
                            <span class="task-info-label">开始时间:</span>
                            <span class="task-info-value">${new Date(task.created_at).toLocaleString()}</span>
                        </div>
                        <div class="task-info-item">
                            <span class="task-info-label">更新时间:</span>
                            <span class="task-info-value">${new Date(task.updated_at).toLocaleString()}</span>
                        </div>
                    </div>
            `;
            
            if (task.error_message) {
                statusHTML += `
                    <div class="task-error-message">
                        <strong>错误信息:</strong> ${task.error_message}
                    </div>
                `;
            }
            
            statusHTML += '</div>';
            return statusHTML;
        }

        // 生成报告
        function generateReport() {
            const query = document.getElementById('searchInput').value.trim() || '智能舆情分析报告';
            
            // 重置日志计数器，因为后台会清空日志文件
            reportLogLineCount = 0;
            
            // 清空控制台显示
            const consoleOutput = document.getElementById('consoleOutput');
            consoleOutput.innerHTML = '<div class="console-line">[系统] 开始生成报告，日志已重置</div>';
            
            // 按钮已移除，无需操作按钮状态
            
            // 在现有状态信息后添加任务进度状态，而不是替换
            addTaskProgressStatus('正在启动报告生成任务...', 'loading');
            
            // 构建请求数据，包含自定义模板（如果有的话）
            const requestData = { query: query };
            if (customTemplate && customTemplate.trim()) {
                requestData.custom_template = customTemplate;
                console.log('使用自定义模板生成报告');
            }
            
            fetch('/api/report/generate', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(requestData)
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    reportTaskId = data.task_id;
                    showMessage('报告生成已启动', 'success');
                    
                    // 更新任务状态显示
                    updateTaskProgressStatus({
                        task_id: data.task_id,
                        query: query,
                        status: 'running',
                        progress: 5, // 初始进度设为5%，确保进度条可见
                        created_at: new Date().toISOString(),
                        updated_at: new Date().toISOString()
                    });
                    
                    // 立即刷新一次日志以确保同步
                    setTimeout(() => {
                        refreshReportLog();
                    }, 500);
                    
                    // 开始轮询任务状态
                    startProgressPolling(data.task_id);
                } else {
                    updateTaskProgressStatus(null, 'error', '启动失败: ' + data.error);
                    // 重置标志允许重新尝试
                    autoGenerateTriggered = false;
                    reportTaskId = null;
                }
            })
            .catch(error => {
                console.error('生成报告失败:', error);
                updateTaskProgressStatus(null, 'error', '生成报告失败: ' + error.message);
                // 重置标志允许重新尝试
                autoGenerateTriggered = false;
                reportTaskId = null;
            });
        }

        // 开始进度轮询
        function startProgressPolling(taskId) {
            if (reportPollingInterval) {
                clearInterval(reportPollingInterval);
            }
            
            reportPollingInterval = setInterval(() => {
                checkTaskProgress(taskId);
            }, 2000);
        }

        // 检查任务进度
        function checkTaskProgress(taskId) {
            fetch(`/api/report/progress/${taskId}`)
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    updateProgressDisplay(data.task);
                    
                    // 在检查进度时也刷新日志
                    refreshReportLog();
                    
                    if (data.task.status === 'completed') {
                        clearInterval(reportPollingInterval);
                        showMessage('报告生成完成！', 'success');
                        
                        // 自动显示报告
                        viewReport(taskId);
                        
                        // 重置自动生成标志，允许下次有新内容时自动生成
                        autoGenerateTriggered = false;
                        reportTaskId = null;
                    } else if (data.task.status === 'error') {
                        clearInterval(reportPollingInterval);
                        showMessage('报告生成失败: ' + data.task.error_message, 'error');
                        
                        // 重置自动生成标志，允许重新尝试
                        autoGenerateTriggered = false;
                        reportTaskId = null;
                    }
                }
            })
            .catch(error => {
                console.error('检查进度失败:', error);
            });
        }

        // 添加任务进度状态（使用固定区域）
        function addTaskProgressStatus(message, status) {
            const taskArea = document.getElementById('taskProgressArea');
            
            if (taskArea) {
                const loadingIndicator = status === 'loading' ? '<span class="report-loading-spinner"></span>' : '';
                
                taskArea.innerHTML = `
                    <div class="task-progress-container">
                        <div class="task-progress-header">
                            ${loadingIndicator}任务状态: ${message}
                        </div>
                    </div>
                `;
            }
        }
        
        // 更新任务进度状态（使用固定区域）
        function updateTaskProgressStatus(task, status = null, errorMessage = null) {
            const taskArea = document.getElementById('taskProgressArea');
            
            if (!taskArea) {
                console.error('taskProgressArea not found');
                return;
            }
            
            if (task) {
                taskArea.innerHTML = renderTaskStatus(task);
            } else if (status && errorMessage) {
                const loadingIndicator = status === 'loading' ? '<span class="report-loading-spinner"></span>' : '';
                const statusBadgeClass = status === 'error' ? 'task-status-error' : 'task-status-running';
                const statusText = status === 'error' ? '错误' : '处理中';
                
                taskArea.innerHTML = `
                    <div class="task-progress-container">
                        <div class="task-progress-header">
                            ${loadingIndicator}任务状态: ${statusText}
                        </div>
                        <div style="margin-top: 10px; font-size: 14px;">
                            ${errorMessage}
                        </div>
                    </div>
                `;
            }
        }

        // 更新进度显示（保持向后兼容）
        function updateProgressDisplay(task) {
            updateTaskProgressStatus(task);
        }

        // 查看报告
        function viewReport(taskId) {
            const reportPreview = document.getElementById('reportPreview');
            reportPreview.innerHTML = '<div class="report-loading"><span class="report-loading-spinner"></span>加载报告中...</div>';
            
            fetch(`/api/report/result/${taskId}`)
            .then(response => {
                if (response.ok) {
                    return response.text();
                } else {
                    throw new Error('报告加载失败');
                }
            })
            .then(rawContent => {
                let htmlContent = rawContent;
                
                // 检查是否是JSON格式的响应（包含html_content字段）
                try {
                    if (rawContent.includes('"html_content":')) {
                        // 提取JSON中的html_content
                        const jsonMatch = rawContent.match(/\{[\s\S]*\}/);
                        if (jsonMatch) {
                            const jsonData = JSON.parse(jsonMatch[0]);
                            if (jsonData.html_content) {
                                htmlContent = jsonData.html_content;
                                // 处理转义字符
                                htmlContent = htmlContent.replace(/\\"/g, '"').replace(/\\n/g, '\n');
                            }
                        }
                    }
                } catch (e) {
                    console.warn('解析JSON格式报告失败，使用原始内容:', e);
                }
                
                // 创建iframe来显示HTML内容
                const iframe = document.createElement('iframe');
                iframe.style.width = '100%';
                iframe.style.border = 'none';
                iframe.style.minHeight = '800px'; // 增加最小高度
                iframe.style.overflow = 'hidden'; // 强制不显示滚动条
                iframe.style.scrollbarWidth = 'none'; // Firefox
                iframe.style.msOverflowStyle = 'none'; // IE and Edge
                iframe.scrolling = 'no'; // 传统方式禁用滚动
                iframe.id = 'report-iframe';
                
                reportPreview.innerHTML = '';
                reportPreview.appendChild(iframe);
                
                // 将HTML内容写入iframe
                iframe.contentDocument.open();
                iframe.contentDocument.write(htmlContent);
                iframe.contentDocument.close();
                
                // 确保iframe内部文档也不显示滚动条
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                if (iframeDoc) {
                    // 设置body样式
                    if (iframeDoc.body) {
                        iframeDoc.body.style.overflow = 'hidden';
                        iframeDoc.body.style.scrollbarWidth = 'none';
                        iframeDoc.body.style.msOverflowStyle = 'none';
                    }
                    // 设置html样式
                    if (iframeDoc.documentElement) {
                        iframeDoc.documentElement.style.overflow = 'hidden';
                        iframeDoc.documentElement.style.scrollbarWidth = 'none';
                        iframeDoc.documentElement.style.msOverflowStyle = 'none';
                    }
                    // 添加CSS规则隐藏webkit滚动条
                    const style = iframeDoc.createElement('style');
                    style.textContent = `
                        body::-webkit-scrollbar, html::-webkit-scrollbar {
                            display: none !important;
                        }
                        body, html {
                            overflow: hidden !important;
                            scrollbar-width: none !important;
                            -ms-overflow-style: none !important;
                        }
                    `;
                    iframeDoc.head.appendChild(style);
                }
                
                // 等待内容加载完成后调整iframe高度
                iframe.onload = function() {
                    setTimeout(() => {
                        try {
                            // 获取iframe内容的实际高度
                            const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                            
                            // 等待所有资源加载完成
                            let contentHeight = 0;
                            
                            // 尝试多种方式获取内容高度
                            if (iframeDoc.body) {
                                contentHeight = Math.max(
                                    iframeDoc.body.scrollHeight || 0,
                                    iframeDoc.body.offsetHeight || 0,
                                    iframeDoc.body.clientHeight || 0
                                );
                            }
                            
                            if (iframeDoc.documentElement) {
                                contentHeight = Math.max(
                                    contentHeight,
                                    iframeDoc.documentElement.scrollHeight || 0,
                                    iframeDoc.documentElement.offsetHeight || 0,
                                    iframeDoc.documentElement.clientHeight || 0
                                );
                            }
                            
                            // 设置iframe高度为内容高度，最小800px
                            const finalHeight = Math.max(contentHeight + 100, 800); // 添加100px的缓冲
                            iframe.style.height = finalHeight + 'px';
                            
                            console.log(`报告iframe高度已调整为: ${finalHeight}px (内容高度: ${contentHeight}px)`);
                            
                            // 确保父容器也能正确显示
                            reportPreview.style.minHeight = finalHeight + 'px';
                            
                        } catch (error) {
                            console.error('调整iframe高度失败:', error);
                            // 如果调整失败，使用更大的默认高度
                            iframe.style.height = '1200px';
                            reportPreview.style.minHeight = '1200px';
                        }
                    }, 1000); // 延迟1秒等待内容完全渲染
                };
                
                // 备用方案：如果onload没有触发，延迟调整高度
                setTimeout(() => {
                    if (iframe.style.height === 'auto' || iframe.style.height === '') {
                        iframe.style.height = '1200px';
                        reportPreview.style.minHeight = '1200px';
                        console.log('使用备用高度设置: 1200px');
                    }
                }, 3000);
            })
            .catch(error => {
                console.error('查看报告失败:', error);
                reportPreview.innerHTML = `
                    <div class="report-loading">
                        报告加载失败: ${error.message}
                    </div>
                `;
            });
        }

        // 检查报告状态（不重新加载整个界面）
        function checkReportStatus() {
            // 只更新状态信息，不重新渲染整个界面
            fetch('/api/report/status')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 更新ReportEngine状态指示器
                    const indicator = document.getElementById('status-report');
                    if (indicator) {
                        if (data.initialized) {
                            indicator.className = 'status-indicator running';
                            appStatus.report = 'running';
                        } else {
                            indicator.className = 'status-indicator';
                            appStatus.report = 'stopped';
                        }
                    }
                    
                    // 更新状态信息（如果存在）
                    updateEngineStatusDisplay(data);
                    
                    showMessage('状态检查完成', 'success');
                } else {
                    showMessage('状态检查失败: ' + data.error, 'error');
                }
            })
            .catch(error => {
                console.error('检查报告状态失败:', error);
                showMessage('状态检查失败: ' + error.message, 'error');
            });
        }
        
        // 更新引擎状态显示（只更新文本内容）
        function updateEngineStatusDisplay(statusData) {
            const statusContent = document.getElementById('engineStatusContent');
            
            if (statusContent) {
                // 确定状态样式
                const statusClass = statusData.initialized ? 'success' : 'error';
                
                // 更新状态信息内容
                let statusHTML = '';
                if (statusData.initialized) {
                    statusHTML = `
                        <strong>ReportEngine状态:</strong> 已初始化<br>
                        <strong>文件检查:</strong> ${statusData.engines_ready ? '准备就绪' : '文件未就绪'}<br>
                        <strong>找到文件:</strong> ${statusData.files_found ? statusData.files_found.join(', ') : '无'}<br>
                        ${statusData.missing_files && statusData.missing_files.length > 0 ? 
                          `<strong>缺失文件:</strong> ${statusData.missing_files.join(', ')}` : ''}
                    `;
                } else {
                    statusHTML = `<strong>ReportEngine状态:</strong> 未初始化`;
                }
                
                // 更新内容和样式
                statusContent.innerHTML = statusHTML;
                statusContent.className = `report-status ${statusClass}`;
            }
        }
    </script>
</body>
</html>
